package uclick.messenger.client.file;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.Socket;
import java.util.Observable;

import uclick.messenger.client.dto.FileDto;
import uclick.messenger.client.protocol.Protocol;

public class Upload extends Observable implements Runnable {
	/**
	 * Logger for this class
	 */
	
	public int getUploaded() {
		return uploaded;
	}



	private FileInputStream fis;

	
	private UploadManager manager;
	private BufferedOutputStream bos;
	long totalSize;
	int uploaded = 0;
	int status;

	private Socket socket;
	
	private String filename;
	private String filepath;
	private String receiver;




	public Upload(FileDto fileDto, Socket socket) {
		manager = UploadManager.getInstance();
		this.filename = getRealFileName(fileDto.getFilename());
		this.filepath = getFilePath(fileDto.getFilename());
		this.totalSize = fileDto.getFilesize();
		this.receiver = fileDto.getMember();
		this.socket = socket;
		upload();
	}
	
	private static String getFilePath(String filename) {
		int indexL = filename.lastIndexOf("\\");
		return filename.substring(0, indexL);
	}

	private static String getRealFileName(String filename) {
		int indexL = filename.lastIndexOf("\\");
		return filename.substring(indexL+1, filename.length());
	}

	public void upload() {
		status = Protocol.RUNNING;
		Thread thread = new Thread(this);
		manager.actionAdd(this);
		thread.start();
		manager.setVisible(true);
	}

	@Override
	public synchronized void run() {
		
		try {
			fis = new FileInputStream(new File(filepath,filename));
			
			bos = new BufferedOutputStream(socket.getOutputStream());
			int count = 1;
			while (status == Protocol.RUNNING) {
				byte[] buffer = this.getBufferSize();
				int read = fis.read(buffer);
				if (read == -1 || uploaded >= totalSize) {
					break;
				}
				bos.write(buffer, 0, read);
				uploaded += read;
				if(count%500 ==0){
					stateChanged();
				}
				count++;
			}
			if(status == Protocol.RUNNING){
				status = Protocol.COMPLETE;
				stateChanged();
			}
		} catch (FileNotFoundException e) {

			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			
			e.printStackTrace();
		}finally {
			try {
				if (fis != null) {
					fis.close();
				}
				if (bos != null) {
					bos.close();
				}
				if(socket!=null){
					socket.close();
				}
			} catch (IOException e) {
			
				e.printStackTrace();
			}
		}
	}

	private void stateChanged() {
		setChanged();
		notifyObservers();
	}

	private byte[] getBufferSize() {
		byte[] buffer;
		if (totalSize - uploaded > Protocol.MAX_BUFFER_SIZE) {
			buffer = new byte[Protocol.MAX_BUFFER_SIZE];
		} else {
			buffer = new byte[(int) (totalSize - uploaded)];
		}
		return buffer;
	}

	public int getTotalSize() {
		return (int)totalSize;
	}

	public String getFileName() {
		String returnString = this.filename;
		return returnString;
	}

	public int getStatus() {
		return status;
	}

	public String getReceiver() {
		return receiver;
	}

	public float getProgress() {
		float returnfloat = ((float) uploaded / totalSize) * 100;
		return returnfloat;
	}

	public void cancel() {
		status = Protocol.CANCELLED;
		stateChanged();
	}

	public void error() {
		status = Protocol.ERROR;
		stateChanged();
	}
}
